package com.cqrt.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cqrt.constant.RTErrorCodeEnum;
import com.cqrt.mapper.RTTaskMapper;
import com.cqrt.mapper.RtWorkItemMapper;
import com.cqrt.service.ProjectChangeService;
import com.cqrt.service.RTProjectService;
import com.cqrt.vo.MIBAVO;
import com.hustcad.plm.pdm.core.handle.exception.SystemErrorCodeEnum;
import com.hustcad.plm.pdm.user.service.TyplmUserService;
import com.hustcad.plm.rpm.model.dto.active.PlusTaskSaveDTO;
import com.hustcad.plm.rpm.model.entity.admin.TyppmProject;
import com.hustcad.plm.rpm.model.entity.change.TyppmChangeInfo;
import com.hustcad.plm.rpm.model.entity.plan.TyppmPlan;
import com.hustcad.plm.rpm.model.vo.change.CreateChangeInfoRequestVO;
import com.hustcad.plm.rpm.model.vo.change.PlanChangeInfoVO;
import com.hustcad.plm.rpm.model.vo.change.PlanUpdateVO;
import com.hustcad.plm.rpm.model.vo.change.TyppmChangeInfoVO;
import com.hustcad.plm.rpm.project.service.TyppmProjectService;
import com.hustcad.plm.rpm.service.change.TyppmChangeInfoService;
import com.hustcad.plm.rpm.service.plan.TyppmPlanActiveService;
import com.hustcad.plm.rpm.service.plan.TyppmPlanService;
import com.lark.oapi.okhttp.*;
import com.ty.basic.constant.TableTypeConstrant;
import com.ty.basic.entity.org.UserDO;
import com.ty.basic.session.TyAccountContext;
import com.ty.ppm.api.service.plan.PlanService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigInteger;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ProjectChangeServiceImpl implements ProjectChangeService {
    @Resource
    private TyppmChangeInfoService typpmChangeInfoService;
    @Resource
    private RTProjectService rtProjectService;
    @Resource
    private RtWorkItemMapper rtWorkItemMapper;
    @Resource
    private TyppmProjectService typpmProjectService;
    @Resource
    private RTTaskMapper rtTaskMapper;
    @Value("${oa.changeInfo.url}")
    private String oaChangeInfoUrl;
    @Value("${tysoft.pdmUrl}")
    private String pdmUrl;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void pauseOrRestartPlan(JSONObject params) throws Exception{
        String type = params.getString("type");
        if(StringUtils.isBlank(type)){
            throw SystemErrorCodeEnum.ARGUMENT_NONE.message("type");
        }
        String projectId = params.getString("projectId");
        if(StringUtils.isBlank(projectId)){
            throw SystemErrorCodeEnum.ARGUMENT_NONE.message("projectId");
        }
        String completeFlowTaskUrl = pdmUrl + "/rest/v1/rt/workflow/completedPlanChangWorkFlow";
        String workFlowContainerId = params.getString("workFlowContainerId");
        if(StringUtils.isBlank(workFlowContainerId)){
            throw SystemErrorCodeEnum.ARGUMENT_NONE.message("workFlowContainerId");
        }
        String finalWorkFlowContainerId = rtWorkItemMapper.selectWorkFlowContainerOidByFlowCode(workFlowContainerId);
        params.put("workFlowContainerId",finalWorkFlowContainerId);
        sentRequestToPDM(params.toJSONString(), completeFlowTaskUrl);
        if("项目暂停".equals(type)){
            updateProjectExecutionStatus(projectId,type);
            typpmProjectService.setProjectStatePaused(Collections.singletonList(projectId));
        }else if("项目恢复".equals(type)){
            updateProjectExecutionStatus(projectId,type);
            typpmProjectService.setProjectStateRecovery(Collections.singletonList(projectId));
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String projectStopOrReStart(JSONObject params) throws Exception{
        String projectOID = params.getString("projectOID");
        String type = params.getString("type");
        TyppmProject typpmProject = typpmProjectService.selectOneByOID(projectOID);
        if (Objects.isNull(typpmProject)){
            throw RTErrorCodeEnum.PROJECT_PARAMETER_NOT_EXIST.getException("项目实体不存在");
        }
        JSONObject jsonStr = new JSONObject();
        JSONObject changFormInfo = new JSONObject();
        if ("项目暂停".equals(type)){
            checkIsExistProjectChange(projectOID);
            changFormInfo.put("field0012","1");
//            updateProjectExecutionStatus(projectOID,type);
//            typpmProjectService.setProjectStatePaused(Collections.singletonList(projectOID));
        }else if ("恢复启动".equals(type)){
            changFormInfo.put("field0060","1");
//            updateProjectExecutionStatus(projectOID,type);
//            typpmProjectService.setProjectStateRecovery(Collections.singletonList(projectOID));
        }
        //申请人
        changFormInfo.put("field0010","-8801123846170458436");
        //编制日期
        changFormInfo.put("field0008", LocalDateTime.now());
        //项目名称
        changFormInfo.put("field0003",typpmProject.getName());

        List<MIBAVO> mibavos = rtTaskMapper.selectIBAById(projectOID);
        //开发等级
        Optional<MIBAVO> grade = mibavos.stream().filter(f -> f.getAttributeenname().equals("DevelopmentLevel")).findAny();
        grade.ifPresent(mibavo -> changFormInfo.put("field0009", mibavo.getAttributevalue()));
        //开发令
        Optional<MIBAVO> developmentOrder = mibavos.stream().filter(f -> f.getAttributeenname().equals("ProjectDevelopmentOrder")).findAny();
        developmentOrder.ifPresent(mibavo -> changFormInfo.put("field0004", mibavo.getAttributevalue()));
        changFormInfo.put("field0008", LocalDateTime.now());
        String code = "WT" + System.currentTimeMillis();
        changFormInfo.put("field0061",code);
        changFormInfo.put("field0066",projectOID);
        changFormInfo.put("field0067",type);
        jsonStr.put("formmain_15442",changFormInfo);
        jsonStr.put("templeteNumber","ty777");
        jsonStr.put("loginName","22051030");
        //调用oa
        String oaUrl = sentRequestToOa(jsonStr.toJSONString(), oaChangeInfoUrl);
        if(StringUtils.isBlank(oaUrl)){
            throw RTErrorCodeEnum.PROJECT_PARAMETER_NOT_EXIST.getException("OA项目变更表单创建失败");
        }

        //创建项目变更单
        JSONObject createChangInfoParams =  new JSONObject();
        createChangInfoParams.put("projectOid",projectOID);
        createChangInfoParams.put("remark",type);
        CreateChangeInfoRequestVO planChangeForm = rtProjectService.createPlanChangeForm(createChangInfoParams);

        //发起审核流程
        TyppmChangeInfo changeInfo = planChangeForm.getChangeInfo();
        String changeInfoOid = changeInfo.getOid();
        startWorkFlow(changeInfoOid, projectOID, code);

        return oaUrl;
    }

    public void startWorkFlow(String changeInfoOid, String projectOID, String code) throws Exception {
        JSONObject startWorkFlowParams = new JSONObject();
        startWorkFlowParams.put("changeInfoOid", changeInfoOid);
        startWorkFlowParams.put("projectOid", projectOID);
        startWorkFlowParams.put("code", code);

        String startFlowUrl = pdmUrl + "/rest/v1/rt/workflow/startPlanChangWorkFlow";
        String startFlowStr = startWorkFlowParams.toJSONString();
        JSONObject responseData = sentRequestToPDM(startFlowStr, startFlowUrl);
        //处理异常。
        if(!"SUCCESS".equals(responseData.getString("result"))){
            throw RTErrorCodeEnum.PROJECT_PARAMETER_NOT_EXIST.getException("项目变更流程发起失败:"+ responseData.getString("data"));
        }
    }

    private JSONObject sentRequestToPDM(String params, String url) throws Exception{
        OkHttpClient client = new OkHttpClient().newBuilder()
                .build();
        String token = loginPlm();
        log.info("============开始发起项目变更流程,参数===================>>:{}", params);
        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create(mediaType, params);
        Request request = new Request.Builder()
                .url(url)
                .method("POST", body)
                .addHeader("Content-Type", "application/json")
                .addHeader("Authorization", token)
                .build();
        Response response = client.newCall(request).execute();
        String result = response.body().string();
        log.info("============开始发起项目变更流程,执行结果===================>>:{}", result);
        return JSONObject.parseObject(result);
    }

    private String loginPlm() throws Exception{
        OkHttpClient client = new OkHttpClient().newBuilder()
                .build();
        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create(mediaType, "{\r\n    \"name\": \"admin\",\r\n    \"password\": \"Ty#123456\",\r\n    \"appID\": \"Chrome(142.0.0.0)\"\r\n}");
        Request request = new Request.Builder()
                .url( pdmUrl + "rest/userService/v1/user/userLogin")
                .method("POST", body)
                .addHeader("Content-Type", "application/json")
                .build();
        Response execute = client.newCall(request).execute();
        Headers headers = execute.headers();
        UserDO userDO = typlmUserService.queryUserByKey(new BigInteger("105"));
        TyAccountContext.setUser(userDO);
        return headers.get("Authorization");
    }

    @Resource
    private TyplmUserService typlmUserService;
    public String sentRequestToOa(String params, String url) throws Exception {
        log.info("============调用oa表单,参数===================>>:{}", params);
        OkHttpClient client = new OkHttpClient().newBuilder().build();
        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create(mediaType, params);
        Request request = new Request.Builder().url(url).method("POST", body).addHeader("Content-Type","application/json").build();
        Response response = client.newCall(request).execute();
        String json = response.body().string();
        if (StrUtil.isNotBlank(json)) {
            JSONObject jsonObject = JSONObject.parseObject(json);
            if (jsonObject.getString("success").equals("true")) {
                return jsonObject.getString("url");
            }
        }
        return null;
    }

    private void checkIsExistProjectChange(String projectId) {
        Map<String, Object> params = new HashMap<>();
        params.put("projectOID", projectId);
        List<TyppmChangeInfoVO> changeInfoList = this.typpmChangeInfoService.queryChangeInfoDTOPageByParams(params, 1, 999).getList();
        if(CollUtil.isNotEmpty(changeInfoList)){
            Set<String> changeInfoStatus = changeInfoList.stream().map(TyppmChangeInfo::getStatus).collect(Collectors.toSet());
            if(changeInfoStatus.contains("编制") || changeInfoStatus.contains("执行中") || changeInfoStatus.contains("草稿")){
                throw RTErrorCodeEnum.PROJECT_PARAMETER_NOT_EXIST.getException("当前项目存在未完成的变更单，不可以发起项目暂停");
            }
        }
    }

    public void updateProjectExecutionStatus(String projectId, String type) {
        BigInteger projectOid = new BigInteger(projectId);
        BigInteger executionStatusId = rtTaskMapper.selectExecutionStatus("执行状态");
        if (type.equals("项目暂停")) {
            rtTaskMapper.updateExecutionStatus("暂停", projectOid, executionStatusId);
        }
        if (type.equals("项目恢复")) {
            rtTaskMapper.updateExecutionStatus("正常", projectOid, executionStatusId);
            List<BigInteger> JobList = rtTaskMapper.selectJobIdByProjectId(projectOid);
            for (BigInteger jobId : JobList) {
                rtTaskMapper.updateExecutionStatus("正常", jobId, executionStatusId);
            }
        }
    }
}
